JS - array - map method
Home

JS - array - map method

JS - array - map method

Mapping is een interessante functionele programmeertechniek voor het bewerken van alle elementen in een array en het retourneren van een array van dezelfde lengte met getransformeerde inhoud. De map methode kan je enigszins vergelijken met een for each lus, maar dan specifiek voor het omzetten van waarden. Eén invoerwaarde komt overeen met één 'getransformeerd' output waarde.

Syntaxis

array.map(function(currentValue,index,arr), thisValue)

Parameters

Parameter Beschrijving
function(currentValue, index, arr) verplicht, een functie die voor elk element in de array uitgevoerd zal worden
Functie argumenten:
Argument Beschrijving
currentValue verplicht: de waarde van het lopende element
index optioneel: de array-index van het lopende element
arr optioneel: de array waarvan het lopende element deel van uitmaakt
thisValue optioneel: een waarde die aan de functie meegegeven kan worden en die als haar "this" waarde kan optreden

Toepassing

Een klassieke, procedurele manier om dat te bewerkstelligen is:

var numberList = [6, 7, 8, 9];
var newNumberList = [];
for(var i = 0; i < numberList.length; i++) {
    newNumberList[i] = numberList[i] * 2;
}
console.log("The list of doubled numbers: ", newNumberList); // [2, 4, 6, 8]

Deze code doet wat er verwacht van wordt maar het kan beter, efficënter. Het is een omslachtige manier om een vrij eenvoudige taak uit te voeren, namelijk het verdubbelen van alle getallen in een array.

Wat als we gewoon de intentie de getallen in de array te verdubbelen konden schrijven en dan aangeven dat op de elementen in de array toe te passen?

var numberList = [3, 2, 6, 5];
var newNumberList = numberList.map(function(number){
    return number * 2;
});
console.log("The doubled numbers are", newNumberList); // [6, 4, 12, 10]

We hebben geen lus meer nodig, en we hoeven niet handmatig de getallen toe te voegen aan een array. We definiëren onze intentie, en laat map het werk doen.

Dit kan ook gemakkelijk worden geketend:

var numberList = [1, 2, 3, 4];
var newNumberList = numberList.map(function(number){
    return number * 2;
}).map(function(number){
    return number + 1;
});
console.log("The list of doubled and incremented numbers: ", newNumberList); // [3, 5, 7, 9]

We kunnen onze intentie ook in een benoemde functie definiëren en verschillende keren na elkaar oproepen. Om bijvoorbeeld een getal te verviervoudigen kunnen we twee keer de methoude double twee keer aan elkaar ketenen:

var numberList = [1, 2, 3, 4];
var double = function(a) {
 return a * 2;
}
var newNumberList = numberList.map(double).map(double);
console.log("The list of doubled and incremented numbers: ", newNumberList); // [4,8,12,16]

Elk getal wordt nu twee keer verdubbeld. We moeten de arrays niet handmatig beheren. We gebruiken gewoon functies die een transformatie toepassen op een enkele waarde.

Je moet wel rekening houden met enkele 'regels' voor de map functies. JavaScript verplicht het niet om die regels na te leven. De regels toch naleven maakt het een stuk makkelijker om te begrijpen wat de code doet.

  1. Het aantal invoerelementen is gelijk aan het aantal uitvoerelementen
    Je kan in de map methode geent 4 waarden invoeren, en er slechts 3 terugkrijgen. Als de bron-array X aantal elementen heeft, zal de resulterende aray ook X aantal elementen bevatten. Elk uitvoerelement komt overeen met het invoerelement in dezelfde positie. Ze worden nooit rond geschud.
  2. De callback functies mogen geen ingevoerde waarden muteren
    Dit betekent dat je moet geen objecten of arrays rechtstreeks vanuit je callback functies mag wijzigen. Je kan best de invoerwaarde van een object of een array klonen het in plaats daarvan, en de kopie ervan wijzigen.

    Op deze manier is er een garantie dat je callback geen neveneffecten veroorzaakt. Dat wil zeggen dat, wat er ook gebeurt in je callback, het alleeninvloed heeft op de kopie. Dit zorgt voor betrouwbare code.

    Je kan een array in Javascript met de array.slice (0) methode klonen. Dat is echter ondiep klonen, namelijk als de waarden in de array zelf arrays of objecten zijn, hebben die nog steeds dezelfde waarden als in de originele array.

    Diepe-klonen maken van een object is ingewikkelder. In een CommonJS omgeving (Node.js, Webpack, Browserify, ...), kan je gebruik maken van de Xtend module. In het slechtste geval maak je zelf een functie:
    functie clone (o) {
       var newO = {};
       for (var keyin o) {
          newO [key] = o[key];
       }
       return newO;
    }
    var cloned = clone(originalObject);
    
    Er is een uitzondering op deze regel, maar we dat later krijgt - gewoon aannemen dat deze regel altijd van toepassing, tenzij anders aangegeven.
  3. Geen neveneffecten veroorzaken
    Doe nooit iets in een map methode dat de 'state' ergens anders wijzigt.
  4. Maar vertragen die callbacks en al dat klonen niet het programma?
    Daarover hoef je je geen zorgen te maken. Deze operaties lopen als een trein in Javascript, vooral in de V8-gebaseerde engines zoals Node.js. Code schrijf je in de eerste plaats voor de leesbaarheid. Prestatie komt op de tweede plaats. Het is veel gemakkelijker om leesbare code te optimaliseren, dan geoptimaliseerde code leesbaar te maken.

Maar wat als ik wil alleen een deel van de waarden te transformeren?

Misschien is uw bron array heeft een aantal waarden die u wilt transformeren, en een aantal waarden die u wil gewoon helemaal weg te gooien. Dat is niet mogelijk met kaart alleen, het aantal invoerwaarden en het aantal uitvoerwaarden voor een kaart gesprek altijd gelijk.

En met map kan je meer dan eenvoudige transformaties uitvoeren. Je methode kan gebruik maken van twee extra parameters, de lopende index en de array zelf. In het volgende voorbeeld:

var starter = [1, 2, 3];
function multiplyByNextElement (value, i, a) {
    var next = i + 1;
    // If at the end of array
    // use the first element
    if (next === a.length) {
        next = 0;
    }
    return value * a[next];
}
var newA = starter.map(multiplyByNextElement);
console.log(newA); // Outputs: [2, 6, 3]

wordt het volgende element gebruikt om de transformatie uit te voeren.

Bronnen

  1. Una Kravets, An Illustrated (and Musical) Guide to Map, Reduce, and Filter Array Methods, Mar 26, 2019
  2. M. David Green, Using Map and Reduce in Functional JavaScript, March 28, 2016

JI
2019-03-30 16:33:08